/*
 * Copyright (c) 2006, 2021, webrx.cn All rights reserved.
 *
 */
package cn.exam;

import org.apache.commons.codec.digest.DigestUtils;

import javax.imageio.ImageIO;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * <p>Project: javaseapp - FileUtils
 * <p>Powered by webrx On 2021-08-17 17:45:36
 * <p>Created by IntelliJ IDEA
 *
 * @author webrx [webrx@126.com]
 * @version 1.0
 * @since 16
 */

public class FileUtils {
    public static int temp = 0;
    public static int num = 0;
    public static long rows = 0;
    public static Map<String, Integer> map = new HashMap<>();
    public static Map<String, Integer> wm = new HashMap<>();

    public FileUtils() {
    }


    public static int count(String dir, String ext) {
        File dirs = new File(dir);
        return count(dirs, ext);
    }

    public static boolean isImage(String img) {
        return isImage(new File(img));
    }

    public static boolean isImage(File img) {
        boolean f = false;
        try {
            var i = ImageIO.read(img);
            int w = i.getWidth();
            int h = i.getHeight();
            int t = i.getType();
            f = true;
        } catch (Exception e) {
            f = false;
        }
        return f;
    }

    public static int count(File dir, String ext) {
        for (File f : dir.listFiles()) {
            if (f.isDirectory()) {
                count(f, ext);
            } else if (f.isFile() && f.getName().endsWith(ext)) {
                ++num;
            }
        }
        return num;
    }

    public static Map<String, Integer> list(File dir) {
        for (File f : dir.listFiles()) {
            if (f.isDirectory()) {
                list(f);
            } else if (f.isFile()) {
                String fn = f.getName();
                int index = fn.lastIndexOf(".");
                String ext = index == -1 ? fn : fn.substring(index);
                if (map.containsKey(ext)) {
                    map.put(ext, map.get(ext) + 1);
                } else {
                    map.put(ext, 1);
                }
            }
        }
        return map;
    }

    public static boolean delFile(String file) {
        return delFile(new File(file));
    }

    public static boolean delFile(File file) {
        boolean f = false;
        if (file.exists()) {
            f = file.delete();
        }
        return f;
    }

    public static void delDir(String dir) {
        delDir(new File(dir));
    }

    public static void delDir(File dir) {
        File[] fs = dir.listFiles();
        if (fs.length == 0) {
            dir.delete(); //删除空目录
        } else {
            for (File f : fs) {
                if (f.isDirectory()) {
                    delDir(f);//再次递归调用，删除目录
                } else if (f.isFile()) {
                    f.delete();//删除文件
                }
            }
        }
        dir.delete();
    }

    public static long countSourceRows(File file) {
        long rows = 0;
        try (BufferedReader br = new BufferedReader(new FileReader(file))) {
            rows = br.lines().count();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return rows;
    }

    public static long countDirRows(File dir) {
        for (File f : dir.listFiles()) {
            if (f.isDirectory()) {
                countDirRows(f);
            } else if (f.isFile() && f.getName().endsWith(".java")) {
                rows += countSourceRows(f);
            }
        }
        return rows;
    }

    public static boolean isSames(String one, String two) {
        return isSames(new File(one), new File(two));
    }

    public static boolean isOk(File one, File two) {
        //apache commons codec 文件 md5
        boolean f = false;
        try {
            FileInputStream fo = new FileInputStream(one);
            FileInputStream ft = new FileInputStream(two);
            String f1 = DigestUtils.md5Hex(fo);
            String f2 = DigestUtils.md5Hex(ft);
            if (f1.equalsIgnoreCase(f2)) {
                f = true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return f;
    }

    public static boolean isSames(File one, File two) {
        boolean f = false;
        if (one.length() == two.length()) {
            try (FileInputStream fo = new FileInputStream(one); FileInputStream ft = new FileInputStream(two)) {
                long i = 0;
                while (fo.read() == ft.read()) {
                    ++i;
                    if (i == one.length() * 0.01) {
                        f = true;
                        break;
                    }
                }

            } catch (Exception e) {
            }
        }
        return f;
    }

    public static String getFileType(String file) {
        return getFileType(new File(file));
    }

    public static String getFileType(File file) {
        String e = "unknow";
        var map = new HashMap<String, String>();
        map.put("jpg", "FFD8FF"); //JPEG (jpg)
        map.put("png", "89504E47");  //PNG (png)
        map.put("gif", "47494638");  //GIF (gif)
        map.put("tif", "49492A00");  //TIFF (tif)
        map.put("bmp", "424D"); //Windows Bitmap (bmp)
        map.put("dwg", "41433130"); //CAD (dwg)
        map.put("html", "68746D6C3E");  //HTML (html)
        map.put("rtf", "7B5C727466");  //Rich Text Format (rtf)
        map.put("xml", "3C3F786D6C");
        map.put("zip", "504B0304");
        map.put("rar", "52617221");
        map.put("psd", "38425053");  //Photoshop (psd)
        map.put("eml", "44656C69766572792D646174653A");  //Email [thorough only] (eml)
        map.put("dbx", "CFAD12FEC5FD746F");  //Outlook Express (dbx)
        map.put("pst", "2142444E");  //Outlook (pst)
        map.put("xls", "D0CF11E0");  //MS Word
        map.put("doc", "D0CF11E0");  //MS Excel 注意：word 和 excel的文件头一样
        map.put("mdb", "5374616E64617264204A");  //MS Access (mdb)
        map.put("wpd", "FF575043"); //WordPerfect (wpd)
        map.put("eps", "252150532D41646F6265");
        map.put("ps", "252150532D41646F6265");
        map.put("pdf", "255044462D312E");  //Adobe Acrobat (pdf)
        map.put("qdf", "AC9EBD8F");  //Quicken (qdf)
        map.put("pwl", "E3828596");  //Windows Password (pwl)
        map.put("wav", "57415645");  //Wave (wav)
        map.put("avi", "41564920");
        map.put("ram", "2E7261FD");  //Real Audio (ram)
        map.put("rm", "2E524D46");  //Real Media (rm)
        map.put("mpg", "000001BA");  //
        map.put("mov", "6D6F6F76");  //Quicktime (mov)
        map.put("asf", "3026B2758E66CF11"); //Windows Media (asf)
        map.put("mid", "4D546864");  //MIDI (mid)
        String ext = getFileHeaderInfo(file, 14);
        for (String k : map.keySet()) {
            if (ext.startsWith(map.get(k))) {
                e = k;
                break;
            }
        }
        return e;
    }

    public static String getFileHeaderInfo(File file, int size) {
        StringBuilder sbu = new StringBuilder();
        byte[] buf = new byte[size];
        try (FileInputStream fis = new FileInputStream(file)) {
            fis.read(buf);
        } catch (IOException e) {
            e.printStackTrace();
        }
        for (byte b : buf) {
            sbu.append(String.format("%02X", b));
        }
        return sbu.toString();
    }

    public static void copyFile(File src, File dst) {
        try (FileInputStream fis = new FileInputStream(src);
             FileOutputStream fos = new FileOutputStream(dst)) {
            int len;
            byte[] buffer = new byte[4096];
            while ((len = fis.read(buffer)) > 0) {
                fos.write(buffer, 0, len);
            }
        } catch (IOException e) {
            // ... handle IO exception
        }
    }

    public static void copyFile(String src, String dst) {
        copyFile(new File(src), new File(dst));
    }

    public static void copyDir(File src, File dst) {
        if (!src.isDirectory()) {
            return;
        }
        if (!dst.exists()) {
            dst.mkdirs();
        }
        File[] files = src.listFiles();
        for (File f : files) {
            if (f.isDirectory()) {
                copyDir(f, new File(dst.getPath(), f.getName()));
            } else if (f.isFile()) {
                copyFile(f, new File(dst.getPath(), f.getName()));
            }
        }
    }

    public static void copyDir(String src, String dst) {
        copyDir(new File(src), new File(dst));
    }

    public static void rename(String file) {
        rename(new File(file));
    }

    public static void rename(File file) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssS");
        Random rand = new Random();
        String fn = String.format("%s_%05d", sdf.format(new Date()), rand.nextInt(99999)) + getExt(file);
        file.renameTo(new File(file.getPath(), fn));
    }

    public static String getExt(String file) {
        String fn = file.toLowerCase();
        int i = fn.lastIndexOf(".");
        return i == -1 ? fn : fn.substring(i);
    }

    public static String getExt(File file) {
        String fn = file.getName().toLowerCase();
        int i = fn.lastIndexOf(".");
        return i == -1 ? fn : fn.substring(i);
    }

    public static Map<String, Integer> countJdk(String file) {
        return countJdk(new File(file));
    }

    public static Map<String, Integer> countJdk(File file) {
        for (File f : file.listFiles()) {
            if (f.isDirectory()) {
                countJdk(f);
            } else if (f.isFile() && f.getName().endsWith(".java")) {
                StringBuilder sbu = new StringBuilder();
                int rows = 0;
                try (var br = new BufferedReader(new FileReader(f))) {
                    while (br.ready()) {
                        sbu.append(br.readLine());
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
                Pattern pattern = Pattern.compile("[a-zA-Z]{2,}");
                Matcher m = pattern.matcher(sbu.toString());

                while (m.find()) {
                    String w = m.group();
                    if (wm.containsKey(w)) {
                        wm.put(w, wm.get(w) + 1);
                    } else {
                        wm.put(w, 1);
                    }
                }
            }
        }
        return wm;
    }
}
